package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.UploadFileUtil;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.xiaoymin.knife4j.core.util.Assert;
import com.qcloud.vod.VodUploadClient;
import com.qcloud.vod.model.VodUploadRequest;
import com.qcloud.vod.model.VodUploadResponse;
import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.vod.v20180717.VodClient;
import com.tencentcloudapi.vod.v20180717.models.ApplyUploadRequest;
import com.tencentcloudapi.vod.v20180717.models.ApplyUploadResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import org.springframework.web.multipart.MultipartFile;

import javax.sound.midi.Track;
import javax.swing.plaf.ToolBarUI;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;
	@Resource
	private AlbumInfoMapper albumInfoMapper;

	@Resource
	private VodService vodService;
	@Resource
	private TrackStatMapper trackStatMapper;

	@Autowired
	private UserInfoFeignClient userInfoFeignClient;
    @Autowired
    private AlbumStatMapper albumStatMapper;

	/**
	 * 批量获取下单付费声音列表
	 * @param trackId
	 * @param trackCount
	 * @param userId
	 * @return
	 */
	@Override
	public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount, Long userId) {
		//1、获取用户已经购买的声音IDList；
		//  获取专辑Id;
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		Result<List<Long>> trackIdListResult = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
		Assert.notNull(trackIdListResult, "远程调用获取用户购买过的声音Id失败");
		List<Long> trackIdList = trackIdListResult.getData();

		List<TrackInfo> trackInfoList = new ArrayList<>();
		if(trackCount>0){
			//买过声音
			//select * from track_info where id> 18026 and album_id=341 and id not in(18027,18028,18029) limit 10;
			LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
			wrapper.eq(TrackInfo::getId,trackId).eq(TrackInfo::getAlbumId,trackInfo.getAlbumId());
			if(trackIdList.size()>0){
				wrapper.notIn(TrackInfo::getId,trackIdList);
			}
			wrapper.last("limit "+trackCount);
			//获取声音集合
			trackInfoList= trackInfoMapper.selectList(wrapper);
		}else{

			if(trackIdList.contains(trackId)){
				//如果多端，其中一个买了，另一个停留在订单页，则会返回空集合

				//  返回数据
				return new ArrayList<>();
			}
			trackInfoList.add(trackInfo);
		}

		return trackInfoList;
	}

	/**
	 * 根据声音Id,获取分集声音列表
	 * @param trackId
	 * @param userId
	 * @return
	 */
	@Override
	public List<Map<String, Object>> findUserTrackPaidList(Long trackId, Long userId) {
		//1、获取声音，根据专辑ID，获取专辑下需要购买的声音集合
		//获取声音
		TrackInfo trackInfo = this.getById(trackId);
		//获取专辑
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		//获取专辑下,大于当前声音,需要购买的声音集合，
		// select * from track_info where album_id= 341 and order_num> orderNum
		LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<TrackInfo>()
				.eq(TrackInfo::getAlbumId, albumInfo.getId())
				.gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());
		List<TrackInfo> trackInfoList = trackInfoMapper.selectList(wrapper);

		//2、获取用户已经买的声音ID列表--feign User服务。select * from user_paid_track where user_id = 30 and album_id = 391;
		Result<List<Long>> trackIdListResult = userInfoFeignClient.findUserPaidTrackList(albumInfo.getId());
		Assert.notNull(trackIdListResult, "远程调用获取用户购买过的声音Id失败");
		List<Long> trackIdList = trackIdListResult.getData();

		//3、排除已经买的声音，获取用户需要购买的声音列表
		//将上述获取到的两个集合做差集; 最终需要付费的声音集合列表;
		List<TrackInfo> infoList = trackInfoList.stream().filter(trackIno -> !trackIdList.contains(trackIno.getId())).collect(Collectors.toList());

		//4、构建分集声音Map
		ArrayList<Map<String, Object>> list = new ArrayList<>();
		int count = infoList.size();
		//构建本集声音
		if(count>=0){
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "本集");
			//  声音的价格; 由专辑来决定;
			map.put("price", albumInfo.getPrice());
			//  购买集数;
			map.put("trackCount", 0);
			//添加到集合
			list.add(map);
		}
		/*//后10集
		if(count>0 && count<=10){
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "后"+count+"集");
			//  声音的价格; 由专辑来决定;
			map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(count))));
			//  购买集数;
			map.put("trackCount", count);

			//添加到集合
			list.add(map);
		}
		//后20集
		if(count>10){
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "后"+count+"集");
			//  声音的价格; 由专辑来决定;
			map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf("10"))));
			//  购买集数;
			map.put("trackCount", 10);
			//添加到集合
			list.add(map);
		}
		if(count>10 && count<=20){
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "后"+count+"集");
			//  声音的价格; 由专辑来决定;
			map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(count))));
			//  购买集数;
			map.put("trackCount", count);

			//添加到集合
			list.add(map);
		}
		//后30集
		if(count>20){
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "后"+count+"集");
			//  声音的价格; 由专辑来决定;
			map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf("20"))));
			//  购买集数;
			map.put("trackCount", 20);

			//添加到集合
			list.add(map);
		}
		if(count>20 && count<=30){
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "后"+count+"集");
			//  声音的价格; 由专辑来决定;
			map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(count))));
			//  购买集数;
			map.put("trackCount", count);

			//添加到集合
			list.add(map);
		}
		//后30集
		if(count>30){
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "后"+count+"集");
			//  声音的价格; 由专辑来决定;
			map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf("30"))));
			//  购买集数;
			map.put("trackCount", 30);

			//添加到集合
			list.add(map);
		}
		if(count>30 && count<=40){
			HashMap<String, Object> map = new HashMap<>();
			map.put("name", "后"+count+"集");
			//  声音的价格; 由专辑来决定;
			map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(count))));
			//  购买集数;
			map.put("trackCount", count);

			//添加到集合
			list.add(map);
		}
*/
		// 处理后10、20、30...集的声音价格，最多显示后50集
		if (count > 0) {
			for (int i = 1; i <= (Math.min(count, 50) + 9) / 10; i++) {
				int start = (i - 1) * 10 + 1;
				int end = Math.min(i * 10, count);

				if (end > 50) {
					break; // 如果超过50集，停止继续添加
				}

				HashMap<String, Object> map = new HashMap<>();
				map.put("name", "后" + end + "集");
				map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(end))));
				map.put("trackCount", end);

				list.add(map);
			}
		}
		return list;
	}

	/**
	 * 更新声音统计信息
	 * @param trackStatMqVo
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void updateTrackStat(TrackStatMqVo trackStatMqVo) {
		try {
			//更新声音播放量,update track_stat stat set stat_num = stat_num + 1 where track_id = 1 and stat_type = '0701' and is_deleted = 0;
			trackStatMapper.updateTrackStat(trackStatMqVo.getCount(),trackStatMqVo.getTrackId(),trackStatMqVo.getStatType());
			if(SystemConstant.TRACK_STAT_PLAY.equals(trackStatMqVo.getStatType())){
				//更新专辑播放量,update album_stat set stat_num = stat_num + 1 where album_id = 1 and stat_type = '0401' and is_deleted = 0;
				albumStatMapper.updateAlbumStat(trackStatMqVo.getCount(),trackStatMqVo.getAlbumId(),SystemConstant.ALBUM_STAT_PLAY);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 根据专辑Id查询声音列表
	 *
	 * @param trackListVoPage
	 * @param albumId
	 * @param userId
	 * @return
	 */
	@Override
	public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> trackListVoPage, Long albumId, Long userId) {
		//1.获取专辑所有声音，
		IPage<AlbumTrackListVo> pageInfo = trackInfoMapper.selectAlbumTrackPage(trackListVoPage, albumId);
		//获取专辑
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		//2.判断用户是否登录
		if (null ==userId) {
			//如果用户未登录
			if(!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())){
				//如果免费专辑之外的所有专辑，那么专辑免费试听数之外的声音都要付费，即orderNum>tracks_for_free的声音，都要付费--->isShowPaidMark = true;
				pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
												.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
			}
			//返回
			return pageInfo;
		}
		if(null!=userId){
			//用户已经登录，
			//声明一个变量，表示是否需要付费
			boolean isNeedPay=false;

			if(SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())){
				//如果专辑付费类型：VIP免费，

				//判断用户是否是VIP
				//如果用户不是VIP、vip已经过期，那么需要付费，isNeedPay=true;
				Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfo(userId);
				Assert.notNull(userInfoVoResult, "远程调用获取用户信息失败");
				UserInfoVo userInfoVo = userInfoVoResult.getData();
				Assert.notNull(userInfoVo, "远程获取userInfoVo失败");

				if(0==userInfoVo.getIsVip()||(1==userInfoVo.getIsVip() && userInfoVo.getVipExpireTime().before(new Date()))){
					isNeedPay=true;
				}
			}else if(SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())){
				//如果专辑付费类型：付费，
				isNeedPay = true;
			}
			//对于付费统一处理，
			if (isNeedPay) {
				//  当前专辑的哪些声音Id 需要付费！ 6-25; 除去免费试听集数;  (判断这个用户是否购买过专辑或购买过单集声音)
				List<AlbumTrackListVo> albumTrackListVoList = pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());

				//获取付费声音IDList集合
				List<Long> trackIdList = albumTrackListVoList.stream().map(albumTrackListVo -> albumTrackListVo.getTrackId()).collect(Collectors.toList());

				//根据用户ID，付费声音IDList,获取用户付费的声音信息 key=trackID，value=1已购买，0未购买，需要付费
				//  远程调用: map.put(trackId,1); map.put(trackId,0); 1:表示已经购买; 0:表示未购买 setIsShowPaidMark(true);
				Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId, trackIdList);
				Assert.notNull(mapResult, "远程调用获取用户付费的声音信息失败");
				Map<Long, Integer> trackmap = mapResult.getData();
				Assert.notNull(trackmap, "远程获取trackmap失败");

				//根据用户付费声音，和所有声音对比，0付费，设为true，1免费，设为false
				for (AlbumTrackListVo albumTrackListVo : albumTrackListVoList) {
					albumTrackListVo.setIsShowPaidMark(trackmap.get(albumTrackListVo.getTrackId())==0);
				}
			}
		}
		return pageInfo;
	}

	/**
	 * 修改声音
	 * @param trackId
	 * @param trackInfoVo
	 */
	@Override
	public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
		//1、获取声音
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		//注意：属性拷贝之前，获取旧声音Id
		String oldMediaFileId = trackInfo.getMediaFileId();
		//2、属性copy
		BeanUtils.copyProperties(trackInfoVo,trackInfo);

		String newMediaFileId = trackInfoVo.getMediaFileId();
		if (!oldMediaFileId.equals(newMediaFileId)) {
			//3、如修改流媒体了，即上传的FileId和 表中声音的FileId 不一致
			//	那么修改media_xx

			//3.1 删除云点播旧声音
			vodService.deleteMedia(oldMediaFileId);
			//3.2 获取最新流媒体
			TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());

			//3.3 修改media_xx
			trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
			trackInfo.setMediaSize(mediaInfo.getSize());
			trackInfo.setMediaDuration(mediaInfo.getDuration());
			trackInfo.setMediaType(mediaInfo.getType());
		}
		//4、更新声音
		trackInfoMapper.updateById(trackInfo);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeTrackInfo(Long trackId) {
		//获取trackInfo
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		//1、删除track，
		trackInfoMapper.deleteById(trackId);

		//2、track重排orderNum，相同album_id，order_num>#{orderNum}，---》orderNum-1
		//update track_info set order_num=order_num-1 where album_id=#{albumId} and order_num>#{orderNum} and is_deleted=0
		trackInfoMapper.updateOrderNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());

		//3、删除vod的流媒体，
		vodService.deleteMedia(trackInfo.getMediaFileId());

		//4、删除相关track_stat，
		//delete from track_stat where track_id=#{trackId} and is_deleted=0
		trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));

		//5、改album_info，的包含声音数include_track_count-1
		//update album_info set include_track_count=include_track_count-1 where album_id=#{albumId} and is_deleted=0
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()-1);
		albumInfoMapper.updateById(albumInfo);

	}

	/**
	 * 根据用户ID，审核状态，声音标题,获取用户声音分页列表
	 * @param trackInfoPage
	 * @param trackInfoQuery
	 * @return
	 */
	@Override
	public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackInfoPage, TrackInfoQuery trackInfoQuery) {
		return trackInfoMapper.selectUserTrackPage(trackInfoPage,trackInfoQuery);
	}

	/**
	 * 保存声音
	 * @param trackInfoVo
	 * @param userId
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveTrackInfo(TrackInfoVo trackInfoVo, long userId) {
		//1、添加trackInfo
		TrackInfo trackInfo = new TrackInfo();
		//1.1属性copy,trackInfoVo->trackInfo
		BeanUtils.copyProperties(trackInfoVo,trackInfo);
		//	给没有默认值的属性赋值
		//	 1.2设置order_num，albumInfo.getById(albumId).include_track_count+1
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		trackInfo.setOrderNum(albumInfo.getIncludeTrackCount()+1);
		//	1.3设置userId,·
		trackInfo.setUserId(userId);
		//	1.4设置流媒体相关参数，vod根据流媒体Id获取mediaFileId、media_duration、media_url、media_size、media_type
		//使用自定义vo：TrackMediaInfoVo,接收腾讯云返回的参数
		TrackMediaInfoVo trackMediaInfoVo=vodService.getMediaInfo(trackInfoVo.getMediaFileId());
		//设置流媒体参数
		trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
		trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
		trackInfo.setMediaSize(trackMediaInfoVo.getSize());
		trackInfo.setMediaType(trackMediaInfoVo.getType());

		//	1.5添加声音
		trackInfoMapper.insert(trackInfo);

		//2、添加trackStat ,声音统计信息
		//赋值播放量，订阅量，点赞量，评论数：使用生成随机数赋值
		this.SaveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
		this.SaveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
		this.SaveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
		this.SaveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);
		/*

		3、修改albumInfo，包含声音数，原有+1
		更新专辑包含声音数，include_track_count+1*/
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()+1);
		albumInfoMapper.updateById(albumInfo);

	}

	/**
	 * 保存专辑统计信息
	 * @param trackId
	 * @param trackStatType
	 */
	public void SaveTrackStat(Long trackId, String trackStatType) {
		TrackStat trackStat = new TrackStat();
		trackStat.setTrackId(trackId);
		trackStat.setStatType(trackStatType);
		trackStat.setStatNum(new Random().nextInt(100000));
		trackStatMapper.insert(trackStat);
	}
}
